/*
 * client.h
 *
 *  Created on: 2021年8月16日
 *      Author: pengzc
 */

#ifndef HTTP_HTTP_CLIENT_H_
#define HTTP_HTTP_CLIENT_H_

#include <cstdlib>
#include <cctype>
#include <string>
#include <curl/curl.h>
#include <http/exception.h>
#include <http/http_request.h>
#include <http/http_response.h>
#include <system/Thread.h>
#include <functional>

namespace http {

struct SpeedLimit {
  int bytes = 0;
  int seconds = 0;

  SpeedLimit(){}
  SpeedLimit(int bytes_, int seconds_): bytes(bytes_), seconds(seconds_) {
  }
};

struct BasicAuth {
  std::string username;
  std::string password;
};

class HTTPClient {
public:
  HTTPClient();
  virtual ~HTTPClient();

  HTTPClient(const HTTPClient&) = delete;
  HTTPClient& operator=(const HTTPClient&) = delete;

  /**
   * 返回false 停止，true继续
   */
  typedef std::function<bool (int64_t dltotal,
      int64_t dlnow, int64_t ultotal, int64_t ulnow)> ProgressCallback;

  HTTPResponse perform(const HTTPRequest& request);
  HTTPResponse perform(const HTTPRequest& request, ProgressCallback progress);
  HTTPResponse perform(const HTTPRequest& request, const std::string& save_path,
      ProgressCallback progress);

  /**
   * 连接超时
   */
  void setConnectTimeout(int ms);

  /**
   * 总超时
   */
  void setTimeout(int ms);

  /**
   * 速度低于bytes/s，持续seconds，中止执行
   */
  void setLowSpeedLimit(int bytes, int seconds);

  void setCAInfoFilePath(const std::string& caInfoFilePath);

  void setSSLVerify(bool verify);

  /**
   * 终止请求
   */
  void terminate();

  void setBasicAuth(const std::string& username, const std::string& password);

  void setDebug(bool debug);

private:
  static ::size_t curlResponseWriteCallback(void *data, ::size_t size,
      ::size_t nmemb, void *userdata);
  static ::size_t header_callback(void *data, ::size_t size, ::size_t nmemb,
      void *userdata);

  static int curlProgressCallback(void *clientp, curl_off_t dltotal,
      curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);

  static int debugTrace(CURL *handle, curl_infotype type, char *data, ::size_t size,
      void *userp);

private:
  CURL* curl_;
  int connection_timeout_;
  int timeout_;
  std::string ca_info_file_path_;
  bool ssl_verify_;
  bool aborted_;
  ProgressCallback progress_callback_;
  Mutex do_mutex_;

  SpeedLimit low_speed_limit_;
  BasicAuth auth_;

  bool debug_;
};

} /* namespace http */

#endif /* JNI_HTTP_CLIENT_H_ */
